//
//  AssetHelper.m
//  DoImagePickerController
//
//  Created by James on 2014. 1. 23..
//

#import "AssetHelper.h"
#import <Contacts/CNContact+Predicates.h>
#import "ContactData.h"
#import "JKFilePathOperationExtension.h"

#define PhotoPathPrefix [[JKFilePathOperationExtension jKTmp] stringByAppendingPathComponent:@"images"]
#define VideoPathPrefix [[JKFilePathOperationExtension jKTmp] stringByAppendingPathComponent:@"videos"]
#define ContactPathPrefix [[JKFilePathOperationExtension jKTmp] stringByAppendingPathComponent:@"contacts"]



@interface AssetHelper ()

@end

@implementation AssetHelper{
    NSMutableArray *_allPhotos;
    NSMutableArray *_allVideos;
    NSMutableArray *_allContacts;
}
#pragma mark - public

+ (AssetHelper *)sharedAssetHelper
{
    static AssetHelper *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[AssetHelper alloc] init];
    });
    
    return _sharedInstance;
}

- (void)fetchAllPhotosAndVideos {
    if (![JKFilePathOperationExtension jkJudgeFileOrFolderExists:PhotoPathPrefix]) {
        [JKFilePathOperationExtension jKCreateFolder:PhotoPathPrefix];
    }
    if (![JKFilePathOperationExtension jkJudgeFileOrFolderExists:VideoPathPrefix]) {
        [JKFilePathOperationExtension jKCreateFolder:VideoPathPrefix];
    }
    // 请求相册权限
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        if (status == PHAuthorizationStatusAuthorized) {
            // 获取所有照片和视频
            [self fetchAssets];
        } else {
            // 处理权限被拒绝的情况
            NSLog(@"相册权限被拒绝");
        }
    }];
}

- (void)fetchAllContacts {
    
    if (![JKFilePathOperationExtension jkJudgeFileOrFolderExists:ContactPathPrefix]) {
        [JKFilePathOperationExtension jKCreateFolder:ContactPathPrefix];
    }

    // 创建联系人存储对象
    CNContactStore *contactStore = [[CNContactStore alloc] init];
    
    // 请求授权
    [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (granted) {
            // 获取联系人列表
            NSArray<CNContact *> *contacts = [self fetchContactsFromContactStore:contactStore];
            
            // 遍历联系人列表
            NSMutableArray<ContactData *> *contactDataArray = [NSMutableArray array];
            for (CNContact *contact in contacts) {
                // 创建ContactData对象保存联系人信息
                ContactData *contactData = [self extractContactDataFromContact:contact];
                [contactDataArray addObject:contactData];
            }
            [self.allContacts addObjectsFromArray:contactDataArray];
            // 将联系人信息保存到本地文件
            NSString *filePath = [self saveContactsToFile:contactDataArray];
            _contactFilePath = filePath;
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.delegate && [self.delegate respondsToSelector:@selector(dataDidChange)]) {
                    [self.delegate dataDidChange];
                }
            });
            NSLog(@"Contacts saved to file: %@", filePath);
        } else {
            NSLog(@"Access to contacts is denied.");
        }
    }];
    
}

- (void)removeAllTmpData{
    if ([JKFilePathOperationExtension jkJudgeFileOrFolderExists:PhotoPathPrefix]) {
        [JKFilePathOperationExtension jKRemovefolder:PhotoPathPrefix];
    }
    if ([JKFilePathOperationExtension jkJudgeFileOrFolderExists:VideoPathPrefix]) {
        [JKFilePathOperationExtension jKRemovefolder:VideoPathPrefix];
    }
    if ([JKFilePathOperationExtension jkJudgeFileOrFolderExists:ContactPathPrefix]) {
        [JKFilePathOperationExtension jKRemovefolder:ContactPathPrefix];
    }
    
    [self.allPhotos removeAllObjects];
    [self.allVideos removeAllObjects];
    [self.allContacts removeAllObjects];
}

- (void)requestImageDataForAsset:(PHAsset *)asset andResultBlock:(ResultBlock)block {
    [[PHImageManager defaultManager] requestImageDataAndOrientationForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, CGImagePropertyOrientation orientation, NSDictionary * _Nullable info) {
        if (imageData) {
            NSNumber *requesrId = [info objectForKey:@"PHImageResultRequestIDKey"];
            // 将 imageData 保存到本地文件
            NSString *filePath = [PhotoPathPrefix stringByAppendingPathComponent:[NSString stringWithFormat:@"IMG_%@.png",requesrId]];
            [imageData writeToFile:filePath atomically:YES];
            if (block) {
                block(filePath);
            }
        }
    }];
}

- (void)requestVideoDataForAsset:(PHAsset *)asset andResultBlock:(ResultBlock)block {
    PHImageManager *imageManager = [PHImageManager defaultManager];
    PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
    options.version = PHVideoRequestOptionsVersionCurrent;
    options.deliveryMode = PHVideoRequestOptionsDeliveryModeFastFormat;
    
    [imageManager requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable avAsset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
        NSNumber *requestId = [info objectForKey:@"PHImageResultRequestIDKey"];
        // 将视频数据保存到本地文件
        NSString *filePath = [VideoPathPrefix stringByAppendingPathComponent:[NSString stringWithFormat:@"Video_%@.mp4",requestId]];

        AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:avAsset presetName:AVAssetExportPresetHighestQuality];
        exportSession.outputURL = [NSURL fileURLWithPath:filePath];
        exportSession.outputFileType = AVFileTypeMPEG4;

        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            if (exportSession.status == AVAssetExportSessionStatusCompleted) {
                if (block) {
                    block(filePath);
                }
            } else {
                NSLog(@"视频保存失败：%@", exportSession.error);
            }
        }];
    }];
}

- (void)saveFileWithPath:(NSString *)filePath {
    if ([filePath containsString:@".plist"]) {
       //保存通讯录
        NSArray *contacts = [NSArray arrayWithContentsOfFile:filePath];
        if (contacts.count > 0) {
            for (NSData *contactData in contacts) {
                NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:contactData];
                ContactData *data = [ContactData contactDataFromDict:dict];
                [self addContactToAddressBook:data];
            }
            
            [JKFilePathOperationExtension jKRemovefile:filePath];
        }
    }else if ([filePath containsString:@".png"]){
        NSData *imageData = [NSData dataWithContentsOfFile:filePath];
        UIImage *image = [UIImage imageWithData:imageData];
        //保存照片
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            [PHAssetChangeRequest creationRequestForAssetFromImage:image];
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            [JKFilePathOperationExtension jKRemovefile:filePath];
        }];
    }else if ([filePath containsString:@".mp4"]){
        //保存视频
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:filePath]];
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            [JKFilePathOperationExtension jKRemovefile:filePath];
        }];
    }else{
        //其他暂时不保存
    }
}
#pragma mark - private

- (void)fetchAssets {
    // 创建一个 PHFetchOptions 对象，可以设置一些过滤条件
    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];

    // 获取所有的照片和视频
    PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsWithOptions:fetchOptions];

    // 遍历结果集，获取每一个 asset（照片或视频）
    [assetsFetchResult enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {
        // 这里可以处理每个 asset，比如获取图片或视频的详细信息
        // asset.localIdentifier 可以用于标识唯一的 asset

        // 判断是照片还是视频
        if (asset.mediaType == PHAssetMediaTypeImage) {
            // 处理照片
//            [self requestImageDataForAsset:asset];
            [self.allPhotos addObject:asset];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.delegate && [self.delegate respondsToSelector:@selector(dataDidChange)]) {
                    [self.delegate dataDidChange];
                }
            });
        } else if (asset.mediaType == PHAssetMediaTypeVideo) {
            // 处理视频
//            [self requestVideoDataForAsset:asset];
            if (asset) {
                [self.allVideos addObject:asset];
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.delegate && [self.delegate respondsToSelector:@selector(dataDidChange)]) {
                    [self.delegate dataDidChange];
                }
            });

        }
    }];
}

- (void)requestImageDataForAsset:(PHAsset *)asset {
    PHImageManager *imageManager = [PHImageManager defaultManager];
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    options.synchronous = YES; // 同步获取数据

    __weak typeof(self) ws = self;
    [imageManager requestImageDataAndOrientationForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, CGImagePropertyOrientation orientation, NSDictionary * _Nullable info) {
        if (imageData) {
            [ws.allPhotos addObject:imageData];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (ws.delegate && [ws.delegate respondsToSelector:@selector(dataDidChange)]) {
                    [ws.delegate dataDidChange];
                }
            });
        }
    }];
}

- (void)requestVideoDataForAsset:(PHAsset *)asset {
    PHImageManager *imageManager = [PHImageManager defaultManager];
    PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
    options.version = PHVideoRequestOptionsVersionCurrent;
    options.deliveryMode = PHVideoRequestOptionsDeliveryModeFastFormat;
    
    __weak typeof(self) ws = self;
    [imageManager requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
        if (asset) {
            [ws.allVideos addObject:asset];
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            if (ws.delegate && [ws.delegate respondsToSelector:@selector(dataDidChange)]) {
                [ws.delegate dataDidChange];
            }
        });
    }];
}

- (void)saveImageDataToLocal:(NSDictionary *)info {
    NSData *imageData = [info objectForKey:@"PHImageFileDataKey"];
    NSNumber *requesrId = [info objectForKey:@"PHImageResultRequestIDKey"];
    // 将 imageData 保存到本地文件
    NSString *filePath = [PhotoPathPrefix stringByAppendingPathComponent:[NSString stringWithFormat:@"IMG_%@.png",requesrId]];
    [imageData writeToFile:filePath atomically:YES];
    [self.allPhotos addObject:filePath];
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(dataDidChange)]) {
            [self.delegate dataDidChange];
        }
    });
}

- (void)saveVideoDataToLocal:(AVAsset *)avAsset andRequestID:(NSNumber *)requestId {
    // 将视频数据保存到本地文件
    NSString *filePath = [VideoPathPrefix stringByAppendingPathComponent:[NSString stringWithFormat:@"Video_%@.mp4",requestId]];

    AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:avAsset presetName:AVAssetExportPresetHighestQuality];
    exportSession.outputURL = [NSURL fileURLWithPath:filePath];
    exportSession.outputFileType = AVFileTypeMPEG4;

    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        if (exportSession.status == AVAssetExportSessionStatusCompleted) {
            [self.allVideos addObject:filePath];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.delegate && [self.delegate respondsToSelector:@selector(dataDidChange)]) {
                    [self.delegate dataDidChange];
                }
            });
        } else {
            NSLog(@"视频保存失败：%@", exportSession.error);
        }
    }];
}


// 从联系人存储中获取联系人列表的方法
- (NSArray<CNContact *> *)fetchContactsFromContactStore:(CNContactStore *)contactStore {
    NSError *error = nil;
    
    // 创建获取联系人的请求
    CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[
        CNContactGivenNameKey,
        CNContactFamilyNameKey,
        CNContactPhoneNumbersKey,
        CNContactEmailAddressesKey,
        CNContactUrlAddressesKey,
        CNContactPostalAddressesKey,
        CNContactBirthdayKey,
        CNContactImageDataKey,
        CNContactImageDataAvailableKey
    ]];
    
    // 执行请求，获取联系人
    NSArray<CNContact *> *contacts = [contactStore unifiedContactsMatchingPredicate:nil keysToFetch:fetchRequest.keysToFetch error:&error];
    
    if (error) {
        NSLog(@"Error fetching contacts: %@", error.localizedDescription);
        return @[];
    }
    
    return contacts;
}

// 从CNContact对象中提取联系人信息的方法
- (ContactData *)extractContactDataFromContact:(CNContact *)contact {
    ContactData *contactData = [[ContactData alloc] init];
    
    contactData.givenName = contact.givenName;
    contactData.familyName = contact.familyName;
    contactData.phoneNumbers = contact.phoneNumbers;
    contactData.emailAddresses = contact.emailAddresses;
    contactData.urlAddresses = contact.urlAddresses;
    contactData.postalAddresses = contact.postalAddresses;
    contactData.birthday = contact.birthday;
    
    // 获取联系人头像数据
    if (contact.imageDataAvailable) {
        contactData.photoData = contact.imageData;
    }
    
    return contactData;
}

// 将联系人信息保存到本地文件的方法
- (NSString *)saveContactsToFile:(NSArray<ContactData *> *)contactDataArray {
    NSString *filePath = [ContactPathPrefix stringByAppendingPathComponent:@"contacts_data.plist"];
    
    // 将ContactData数组转为字典数组
    NSMutableArray *contactDictArray = [NSMutableArray array];
    for (ContactData *contactData in contactDataArray) {
        NSDictionary *contactDict = [contactData dictionaryFromContactData];
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:contactDict];
        [contactDictArray addObject:data];
    }
    
    // 将字典数组写入文件
    if (![contactDictArray writeToFile:filePath atomically:YES]) {
        NSLog(@"Error saving contacts to file.");
        return nil;
    }
    
    return filePath;
}

- (void)addContactToAddressBook:(ContactData *)data {
    // 创建一个联系人
    CNMutableContact *contact = [[CNMutableContact alloc] init];
    
    // 设置联系人的属性
    contact.givenName = data.givenName;
    contact.familyName = data.familyName;
    if ([data.phoneNumbers isKindOfClass:[NSArray class]]) {
        contact.phoneNumbers = data.phoneNumbers;
    }
    if ([data.emailAddresses isKindOfClass:[NSArray class]]) {
        contact.emailAddresses = data.emailAddresses;
    }
    if ([data.urlAddresses isKindOfClass:[NSArray class]]) {
        contact.urlAddresses = data.urlAddresses;
    }
    if ([data.postalAddresses isKindOfClass:[NSArray class]]) {
        contact.postalAddresses = data.postalAddresses;
    }
    if ([data.birthday isKindOfClass:[NSDateComponents class]]) {
        contact.birthday = data.birthday;
    }
    if ([data.photoData isKindOfClass:[NSData class]]) {
        contact.imageData = data.photoData;
    }
    
    
    // 创建写入请求
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest addContact:contact toContainerWithIdentifier:nil];
    
    // 执行写入请求
    NSError *error = nil;
    CNContactStore *contactStore = [[CNContactStore alloc] init];
    [contactStore executeSaveRequest:saveRequest error:&error];
    
    if (error) {
        NSLog(@"写入通讯录出错：%@", error.localizedDescription);
    } else {
        NSLog(@"联系人成功添加到通讯录");
    }
}



- (NSMutableArray *)allPhotos{
    if(!_allPhotos){
        _allPhotos = [[NSMutableArray alloc] init];
    }
    return _allPhotos;
}

- (NSMutableArray *)allVideos{
    if(!_allVideos){
        _allVideos = [[NSMutableArray alloc] init];
    }
    return _allVideos;
}

- (NSMutableArray *)allContacts{
    if(!_allContacts){
        _allContacts = [[NSMutableArray alloc] init];
    }
    return _allContacts;
}


@end
